
// ag_win32.cpp
// win32-gdi hello ~

#include "ag_win32.hpp"
 
#include <iostream>
#include <string>
#include <stdio.h>
#include <thread>



// ----- 窗口样式 -----
//WS_CAPTION | WS_POPUPWINDOW | WS_VISIBLE,
#define WINDOW_Without_Title_Bar WS_POPUP | WS_VISIBLE
#define WINDOW_Title_Bar WS_OVERLAPPEDWINDOW | WS_VISIBLE
#define WINDOW_Title_Bar2 WS_CAPTION | WS_POPUPWINDOW | WS_VISIBLE


// Windows Hello ~
// Aeno Graphics Api
// Window
 
namespace Aeno
{
    Window::Window(){}
    Window::~Window(){}

    Window::Window(WindowConfig config)
    {
        is_vsync_bool_      = false;
        is_fullscreen_bool_ = false;
        is_middle_bool_     = false;

        title_  = "";
        width_  = 0;
        height_ = 0;
        pos_x_  = 0;
        pos_y_  = 0;

        win_config_ = config;
        title_      = config.title;
        width_      = config.width;
        height_     = config.height;

		win_handle_ = HWND();

        // std::thread winThread{ &Window::winControl_ ,this };
        // winThread.detach();
    }
    
    std::string Window::getTitle()
    { return title_; }

    void Window::setTitle(std::string title)
    {
        // SetWindowTextA(handle_, title.data());
        SetWindowText(win_handle_, title.data());
        title_ = title;
    }

    uint32_t Window::getWidth()
    { return width_; }

    uint32_t Window::getHeight()
    { return height_; }

    

    

    

    // GetWindowRect(hWnd, &rect);
    // SetWindowPos(hWnd, NULL, x, y, widthx, heightx, SWP_NOZORDER | SWP_SHOWWINDOW);
    // SetWindowLong(hWnd, GWL_STYLE, GetWindowLong(hWnd, GWL_STYLE) & ~WS_CAPTION);
    // SetWindowPos(hWnd, NULL, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER | SWP_DRAWFRAME);
    // RECT recta;
    // GetWindowRect(hWnd, &recta);
    // printf("%d", rect.right - rect.left);
    // CW_USEDEFAULT

    

    void Window::CreateMainWindow()
    {
        HINSTANCE  hinst = GetModuleHandle(nullptr);
        WNDCLASS      wc = { 0 };
        wc.lpszClassName = "AenoWindowCls";
        wc.style         = CS_HREDRAW | CS_VREDRAW /* | CS_DBLCLKS */ ;
        wc.lpfnWndProc   = staticWndProc;
        wc.cbClsExtra    = 0;
        wc.cbWndExtra    = 0;
        wc.hInstance     = hinst;
        wc.hIcon         = LoadIcon(nullptr, IDI_APPLICATION);
        wc.hCursor       = LoadCursor(nullptr, IDC_ARROW);
        wc.lpszMenuName  = nullptr;
        wc.hbrBackground = (HBRUSH)::GetStockObject(BLACK_BRUSH);
        RegisterClass(&wc); // Window-CLASS

        // ----- 画布尺寸一统 -----
        RECT rect = { 0, 0, int(win_config_.width), int(win_config_.height) };
        AdjustWindowRect(&rect, WINDOW_Without_Title_Bar, 0);
        int WinWidth = rect.right - rect.left;
        int WinHeight = rect.bottom - rect.top;

        // 获取屏幕分辨率
		int screenWidth = ::GetSystemMetrics(SM_CXSCREEN);
		int screenHeight = ::GetSystemMetrics(SM_CYSCREEN);
        // width_ = GetSystemMetrics(SM_CXSCREEN);
	    // height_ = GetSystemMetrics(SM_CYSCREEN);

        // ----- 窗口在屏幕中间 -----
        pos_x_ = (screenWidth - WinWidth) / 2;
        pos_y_ = (screenHeight - WinHeight) / 2;

        //  config_.title.c_str(), 

        win_handle_ = CreateWindow( "AenoWindowCls", win_config_.title.data(), WINDOW_Without_Title_Bar, pos_x_, pos_y_, WinWidth, WinHeight, nullptr, nullptr, hinst, nullptr );
        
        // 显式销毁窗口
        // DestroyWindow(win_handle_);
    }

   
    
    

    HWND Window::getHWND()
    {
        return win_handle_;
    }

    bool Window::update()
    {
        MSG msg; 
        BOOL bQuit = 0;
        // 渲染循环 检查消息
        while (!bQuit)
        {
            if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
            {
                if (msg.message == WM_QUIT)
                {
                    // 处理或发送消息
                    bQuit = TRUE;
                }
                else
                {
                    TranslateMessage(&msg);
                    DispatchMessage(&msg);
                }
            }
            else
            {

            }
        }
        // 显式销毁窗口
        DestroyWindow(win_handle_);
        return msg.wParam;
    }

    // setVSyncBool
    void Window::setFullScreenBool(bool full_screen_bool)
    {
        is_fullscreen_bool_ = full_screen_bool;

        if(is_fullscreen_bool_)
        { 
			// LONG winStyle =  GetWindowLong(win_handle_, GWL_STYLE);
			SetWindowLong(win_handle_, GWL_STYLE, WS_POPUP);
			RECT rect;
			GetWindowRect(GetDesktopWindow(), &rect);

            int x  = (int)rect.left;
            int y  = (int)rect.top;
            int cw = (int)(rect.right - rect.left);
            int ch = (int)(rect.bottom - rect.top);

			SetWindowPos( win_handle_, HWND_TOPMOST, x, y, cw, ch, SWP_SHOWWINDOW );
            ShowWindow( win_handle_, SW_SHOWNORMAL );
            width_ = cw; height_ = ch;
			printf("x:%d x:%d cx:%d cy:%d \n", x,y,cw,ch);
        }
    }

    void Window::setVSyncBool(bool vsync_bool)
    {
        is_vsync_bool_ = vsync_bool;
    }
    
    void Window::setFPS(uint32_t fps)
    {
        fps_ = fps;
    }

    void Window::winControl_(Window* window)
    {
        // 多线程
        // 程序
    }


  
    Renderer* Window::s_pRenderer = nullptr;



    LRESULT CALLBACK Window::staticWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
    {
        int xPos = 0, yPos = 0;
        HDC hDC;
        switch (message)
        {
            case WM_MOUSEMOVE:
                // xPos = (int)GET_X_LPARAM(lParam), yPos = (int)GET_Y_LPARAM(lParam);
                // printf("当前的鼠标坐标为：x:%d,y:%d\n",xPos,yPos);
            case WM_SIZE:
                if (wParam != SIZE_MINIMIZED)
                {
                    //g_Width = LOWORD(lParam);
                    //g_Height = HIWORD(lParam);
                    // printf("WM_SIZE: w:%d, h:%d\n", LOWORD(lParam), HIWORD(lParam));
                    
                }
                return 0;

            case WM_TIMER:
                // 定时器消息，更新动画并重新绘制窗口
               if (s_pRenderer) {
                   s_pRenderer->UpdateAnimation();// 更新动画状态
                   RECT clientRect;
                   GetClientRect(hWnd, &clientRect);
                   InvalidateRect(hWnd, &clientRect, FALSE);
                   // printf("e");
               }
                return 0;

            case WM_PAINT:
                {
                    // ---- 最初开始 ----
                    PAINTSTRUCT ps;
                    HDC         hdc = BeginPaint(hWnd, &ps);


                    // 进行渲染
                    if (s_pRenderer) {
                        
                        s_pRenderer->SetDeviceContext(hdc);
                        s_pRenderer->ClearScreen();
                        // 根据动画状态绘制椭圆
                        
                        s_pRenderer->RenderEllipse(s_pRenderer->m_animationX+200, s_pRenderer->m_animationX+200, s_pRenderer->m_ellipseWidth+200, s_pRenderer->m_ellipseHeight+200); 
                        s_pRenderer->RenderEllipse(s_pRenderer->m_animationX, s_pRenderer->m_animationX, s_pRenderer->m_ellipseWidth, s_pRenderer->m_ellipseHeight); 
                        s_pRenderer->RenderEllipse(s_pRenderer->m_animationX+500, s_pRenderer->m_animationX+200, s_pRenderer->m_ellipseWidth+200, s_pRenderer->m_ellipseHeight+200); 
                        s_pRenderer->Present();
                    }

                    EndPaint(hWnd, &ps);
                } break;
            // case WM_ERASEBKGND:
            // 
            //     return 0;

            case WM_CREATE:
                SetTimer(hWnd, 1, 1, nullptr);
                return 0;
            case WM_CLOSE:
                PostQuitMessage(0);
                return 0;
            case WM_DESTROY:
                return 0;
            case WM_KEYDOWN:
                switch (wParam)
                {
                    case VK_ESCAPE:
                        PostQuitMessage(0);
                        return 0;
                    case VK_TAB:
                        printf("Tab\n");
                }
                return 0;
            default:
                return DefWindowProc(hWnd, message, wParam, lParam);
        }
        return 0;
    }





   
}
















// Color
namespace Aeno
{
    Color::Color() : r(1.f), g(1.f), b(1.f), a(1.f) {}
    Color::~Color(){}

	// Color
	Color::Color(float r, float g, float b, float a) : r(r), g(g), b(b), a(a) {}

	Color::Color(uint32_t rgb, float a)
	{
		setColor(rgb, a);
	}

	void Color::setColor(float r, float g, float b, float a)
	{
		this->r = r; this->g = g; this->b = b; this->a = a;
	}

	void Color::setColor(uint32_t rgb, float na)
	{
		//取完位后再除以255将范围取到0~1
		r = (rgb >> 16) / 255.0f;					//相当于0xAABBCC 取0xAA
		g = ((rgb & ~0xFF00FF) >> 8) / 255.0f;		//相当于0xAABBCC 取0xBB
		b = (rgb & ~0xFFFF00) / 255.0f;				//相当于0xAABBCC 取0xCC
		a = na;
	}
	


	// RGB
	uint32_t RGB_U(uint8_t red, uint8_t green, uint8_t blue)
	{
		// return (red << 16) + (green << 8) + blue;
    	return (red << 16) | (green << 8) | blue;
	}

	uint32_t RGB_C(Color color)
	{
		uint8_t red = uint8_t(color.r * 255);
		uint8_t green = uint8_t(color.g * 255);
		uint8_t blue = uint8_t(color.b * 255);
		// return (red << 16) + (green << 8) + blue;
		return (red << 16) | (green << 8) | blue;
	}

	uint32_t RGB_F(float red, float green, float blue)
	{
		return RGB_C({red,green,blue});
	}


	// RGBA
	uint32_t RGBA_U(uint8_t red, uint8_t green, uint8_t blue, uint8_t alpha)
	{
		// return (red << 16) + (green << 8) + blue;
		// return (a << 24) | (red << 16) | (green << 8) | blue;
    	return (alpha << 24) | (red << 16) | (green << 8) | blue;
	}

	uint32_t RGBA_C(Color color)
	{
		uint8_t red = uint8_t(color.r * 255);
		uint8_t green = uint8_t(color.g * 255);
		uint8_t blue = uint8_t(color.b * 255);
		uint8_t alpha = uint8_t(color.a * 255);

		// return (red << 16) + (green << 8) + blue;
		return (alpha << 24) | (red << 16) | (green << 8) | blue;
	}

	uint32_t RGBA_F(float red, float green, float blue, float alpha)
	{
		return RGBA_C({red,green,blue, alpha});
	}
    
}






// Renderer
namespace Aeno
{
   // Renderer::Renderer(/* args */)
   // {
   //     clear_color_ = Color(0.0f, 0.0f, 0.0f, 1.0f);
   //     // Color::Black;
   // }
   // 
   // Renderer::~Renderer()
   // {

   // }

    Renderer::Renderer(HWND hWnd)
    {
        // m_win = win;
        m_hWnd = hWnd;
        
        m_clear_color = RGB( 255, 255, 255 );
    }

    // Renderer::Renderer(HWND hWnd) : m_hWnd(hWnd), m_clearColor(RGB(255, 255, 255)) {}

    void Renderer::ClearScreen() {
        RECT clientRect;
        GetClientRect(m_hWnd, &clientRect);
        FillRect(m_hMemDC, &clientRect, CreateSolidBrush(m_clear_color));
    }

    void Renderer::RenderEllipse(int x, int y, int w, int h) {
        Ellipse(m_hMemDC, x, y, w, h);
    }

    void Renderer::SetDeviceContext(HDC hdc) {
        m_hMemDC = hdc;
    }

    void Renderer::SetClearColor(COLORREF color) {
        m_clear_color = color;
    }

    void Renderer::Present() {
        RECT clientRect;
        HDC hdc = GetDC(m_hWnd);
        GetClientRect(m_hWnd, &clientRect);
        BitBlt(hdc, 0, 0, clientRect.right - clientRect.left, clientRect.bottom - clientRect.top, m_hMemDC, 0, 0, SRCCOPY);
        ReleaseDC(m_hWnd, hdc);

        // BitBlt
    }

    void Renderer::UpdateAnimation() {
        m_animationX += m_animationSpeed;
        if (m_animationX > 600) {
            m_animationX = -m_ellipseWidth; // 重置到屏幕左侧
        }
    }





    void Renderer::SetAnimationSpeed(int speed) {
        m_animationSpeed = speed;
    }

    void Renderer::SetEllipseSize(int width, int height) {
        m_ellipseWidth = width;
        m_ellipseHeight = height;
    }











   // void Renderer::ClearScreen(HWND hWnd) {
//
   //     HDC hdc = GetDC(hWnd);
   //     RECT rect;
   //     GetClientRect(hWnd, &rect);
   //     HBRUSH hBrush = CreateSolidBrush(RGB(clear_color_.r,clear_color_.g,clear_color_.b));
   //     FillRect(hdc, &rect, hBrush);
   //     DeleteObject(hBrush);
   //     ReleaseDC(hWnd, hdc);
   // }

}